"""
OpenCV服务

提供OpenCV相关的高级服务功能。
"""

import asyncio
import os
from typing import Dict, List, Any, Optional
from pathlib import Path
import logging
import json

from src.core.di import Inject, Service
from src.modules.analyzers import OpenCVAnalyzer


@Service("opencv_service")
class OpenCVService:
    """
    OpenCV服务
    
    提供高级的OpenCV分析和批处理功能。
    """
    
    def __init__(self,
                 analyzer: OpenCVAnalyzer = Inject(OpenCVAnalyzer),
                 config: Dict[str, Any] = Inject("config"),
                 logger: logging.Logger = Inject("logger")):
        self.analyzer = analyzer
        self.config = config
        self.logger = logger
        
        # 批处理配置
        self.max_concurrent_jobs = config.get("opencv", {}).get("max_concurrent_jobs", 2)
        self.analysis_cache = {}
    
    async def batch_analyze_videos(self,
                                  video_files: List[str],
                                  output_dir: Optional[str] = None,
                                  save_results: bool = True) -> Dict[str, Any]:
        """
        批量分析视频
        
        Args:
            video_files: 视频文件列表
            output_dir: 输出目录
            save_results: 是否保存结果到文件
        
        Returns:
            批处理结果
        """
        self.logger.info(f"开始批量分析 {len(video_files)} 个视频文件")
        
        if output_dir:
            os.makedirs(output_dir, exist_ok=True)
        
        # 创建任务
        tasks = []
        for video_file in video_files:
            task = self._create_analysis_task(video_file, output_dir, save_results)
            tasks.append(task)
        
        # 并发执行任务
        semaphore = asyncio.Semaphore(self.max_concurrent_jobs)
        
        async def limited_task(task):
            async with semaphore:
                return await task
        
        results = await asyncio.gather(
            *[limited_task(task) for task in tasks],
            return_exceptions=True
        )
        
        # 整理结果
        success_count = 0
        error_count = 0
        all_analyses = {}
        errors = []
        
        for i, result in enumerate(results):
            video_file = video_files[i]
            if isinstance(result, Exception):
                error_count += 1
                errors.append({
                    "file": video_file,
                    "error": str(result)
                })
                self.logger.error(f"分析文件失败 {video_file}: {result}")
            else:
                success_count += 1
                all_analyses[video_file] = result
        
        # 生成汇总报告
        summary = self._generate_analysis_summary(all_analyses)
        
        batch_result = {
            "total_files": len(video_files),
            "success_count": success_count,
            "error_count": error_count,
            "analyses": all_analyses,
            "summary": summary,
            "errors": errors
        }
        
        # 保存批处理结果
        if output_dir and save_results:
            summary_file = os.path.join(output_dir, "batch_analysis_summary.json")
            with open(summary_file, 'w', encoding='utf-8') as f:
                json.dump(batch_result, f, indent=2, ensure_ascii=False, default=str)
        
        self.logger.info(f"批量分析完成: 成功 {success_count}, 失败 {error_count}")
        return batch_result
    
    async def _create_analysis_task(self,
                                   video_file: str,
                                   output_dir: Optional[str],
                                   save_results: bool) -> Dict[str, Any]:
        """创建分析任务"""
        try:
            # 检查缓存
            cache_key = f"{video_file}:{os.path.getmtime(video_file)}"
            if cache_key in self.analysis_cache:
                self.logger.info(f"使用缓存结果: {video_file}")
                return self.analysis_cache[cache_key]
            
            # 执行分析
            analysis_result = await self.analyzer.analyze_video(video_file)
            
            # 缓存结果
            self.analysis_cache[cache_key] = analysis_result
            
            # 保存单个分析结果
            if output_dir and save_results:
                file_name = Path(video_file).stem
                result_file = os.path.join(output_dir, f"{file_name}_analysis.json")
                with open(result_file, 'w', encoding='utf-8') as f:
                    json.dump(analysis_result, f, indent=2, ensure_ascii=False, default=str)
            
            return analysis_result
            
        except Exception as e:
            self.logger.error(f"分析任务失败 {video_file}: {e}")
            raise
    
    def _generate_analysis_summary(self, analyses: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
        """生成分析汇总"""
        if not analyses:
            return {}
        
        # 收集统计数据
        total_scenes = 0
        total_frames = 0
        total_duration = 0.0
        brightness_values = []
        contrast_values = []
        motion_values = []
        scene_counts = []
        
        for video_file, analysis in analyses.items():
            total_scenes += analysis.get("scene_count", 0)
            total_frames += analysis.get("frame_count", 0)
            total_duration += analysis.get("video_info", {}).get("duration", 0)
            
            scene_counts.append(analysis.get("scene_count", 0))
            
            # 提取特征统计
            features = analysis.get("features", {})
            color_features = features.get("color_features", {})
            motion_analysis = analysis.get("motion_analysis", {})
            
            if "average_brightness" in color_features:
                brightness_values.append(color_features["average_brightness"])
            if "average_contrast" in color_features:
                contrast_values.append(color_features["average_contrast"])
            if "average_motion" in motion_analysis:
                motion_values.append(motion_analysis["average_motion"])
        
        # 计算汇总统计
        import numpy as np
        
        summary = {
            "total_videos": len(analyses),
            "total_scenes": total_scenes,
            "total_frames": total_frames,
            "total_duration": total_duration,
            "average_scenes_per_video": total_scenes / len(analyses),
            "average_duration_per_video": total_duration / len(analyses),
            "scene_distribution": {
                "min": int(np.min(scene_counts)) if scene_counts else 0,
                "max": int(np.max(scene_counts)) if scene_counts else 0,
                "mean": float(np.mean(scene_counts)) if scene_counts else 0.0,
                "std": float(np.std(scene_counts)) if scene_counts else 0.0
            }
        }
        
        if brightness_values:
            summary["brightness_statistics"] = {
                "min": float(np.min(brightness_values)),
                "max": float(np.max(brightness_values)),
                "mean": float(np.mean(brightness_values)),
                "std": float(np.std(brightness_values))
            }
        
        if contrast_values:
            summary["contrast_statistics"] = {
                "min": float(np.min(contrast_values)),
                "max": float(np.max(contrast_values)),
                "mean": float(np.mean(contrast_values)),
                "std": float(np.std(contrast_values))
            }
        
        if motion_values:
            summary["motion_statistics"] = {
                "min": float(np.min(motion_values)),
                "max": float(np.max(motion_values)),
                "mean": float(np.mean(motion_values)),
                "std": float(np.std(motion_values))
            }
        
        return summary
    
    async def detect_similar_scenes(self,
                                   video_files: List[str],
                                   similarity_threshold: float = 0.8) -> List[Dict[str, Any]]:
        """
        检测相似场景
        
        Args:
            video_files: 视频文件列表
            similarity_threshold: 相似度阈值
        
        Returns:
            相似场景组列表
        """
        self.logger.info(f"检测 {len(video_files)} 个视频中的相似场景")
        
        # 分析所有视频
        all_scenes = {}
        for video_file in video_files:
            scenes = await self.analyzer.detect_scenes(video_file)
            all_scenes[video_file] = scenes
        
        # 比较场景相似度
        similar_groups = []
        processed_scenes = set()
        
        for video1, scenes1 in all_scenes.items():
            for i, scene1 in enumerate(scenes1):
                scene1_id = f"{video1}:{i}"
                if scene1_id in processed_scenes:
                    continue
                
                similar_scenes = [{"video": video1, "scene_index": i, "scene": scene1}]
                processed_scenes.add(scene1_id)
                
                # 与其他场景比较
                for video2, scenes2 in all_scenes.items():
                    if video2 == video1:
                        continue
                    
                    for j, scene2 in enumerate(scenes2):
                        scene2_id = f"{video2}:{j}"
                        if scene2_id in processed_scenes:
                            continue
                        
                        # 计算相似度（简化实现）
                        similarity = self._calculate_scene_similarity(scene1, scene2)
                        
                        if similarity >= similarity_threshold:
                            similar_scenes.append({"video": video2, "scene_index": j, "scene": scene2})
                            processed_scenes.add(scene2_id)
                
                if len(similar_scenes) > 1:
                    similar_groups.append({
                        "group_id": len(similar_groups),
                        "scene_count": len(similar_scenes),
                        "scenes": similar_scenes,
                        "average_duration": sum(s["scene"]["duration"] for s in similar_scenes) / len(similar_scenes)
                    })
        
        self.logger.info(f"检测到 {len(similar_groups)} 个相似场景组")
        return similar_groups
    
    def _calculate_scene_similarity(self, scene1: Dict[str, Any], scene2: Dict[str, Any]) -> float:
        """计算场景相似度（简化实现）"""
        # 基于时长的相似度
        duration1 = scene1.get("duration", 0)
        duration2 = scene2.get("duration", 0)
        
        if duration1 == 0 or duration2 == 0:
            return 0.0
        
        duration_ratio = min(duration1, duration2) / max(duration1, duration2)
        
        # 可以添加更多特征比较，如颜色直方图、运动特征等
        return duration_ratio
    
    async def generate_video_report(self,
                                   video_file: str,
                                   output_path: str) -> str:
        """
        生成视频分析报告
        
        Args:
            video_file: 视频文件路径
            output_path: 报告输出路径
        
        Returns:
            报告文件路径
        """
        self.logger.info(f"生成视频分析报告: {video_file}")
        
        # 执行完整分析
        analysis = await self.analyzer.analyze_video(video_file)
        
        # 生成HTML报告
        html_content = self._generate_html_report(video_file, analysis)
        
        # 保存报告
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        
        self.logger.info(f"报告已生成: {output_path}")
        return output_path
    
    def _generate_html_report(self, video_file: str, analysis: Dict[str, Any]) -> str:
        """生成HTML报告"""
        video_info = analysis.get("video_info", {})
        features = analysis.get("features", {})
        scenes = analysis.get("scenes", [])
        motion_analysis = analysis.get("motion_analysis", {})
        
        html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>视频分析报告 - {Path(video_file).name}</title>
            <meta charset="utf-8">
            <style>
                body {{ font-family: Arial, sans-serif; margin: 20px; }}
                .header {{ background-color: #f0f0f0; padding: 20px; border-radius: 5px; }}
                .section {{ margin: 20px 0; }}
                .metric {{ display: inline-block; margin: 10px; padding: 10px; background-color: #e8f4f8; border-radius: 3px; }}
                table {{ border-collapse: collapse; width: 100%; }}
                th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
                th {{ background-color: #f2f2f2; }}
            </style>
        </head>
        <body>
            <div class="header">
                <h1>视频分析报告</h1>
                <p><strong>文件:</strong> {video_file}</p>
                <p><strong>分析时间:</strong> {analysis.get('analysis_metadata', {}).get('timestamp', 'N/A')}</p>
            </div>
            
            <div class="section">
                <h2>基本信息</h2>
                <div class="metric">时长: {video_info.get('duration', 0):.2f}秒</div>
                <div class="metric">分辨率: {video_info.get('width', 0)}x{video_info.get('height', 0)}</div>
                <div class="metric">帧率: {video_info.get('fps', 0):.2f} FPS</div>
                <div class="metric">总帧数: {video_info.get('frame_count', 0)}</div>
            </div>
            
            <div class="section">
                <h2>场景分析</h2>
                <div class="metric">场景数量: {len(scenes)}</div>
                <div class="metric">平均场景时长: {sum(s.get('duration', 0) for s in scenes) / max(len(scenes), 1):.2f}秒</div>
                
                <h3>场景详情</h3>
                <table>
                    <tr><th>场景</th><th>开始时间</th><th>结束时间</th><th>时长</th><th>变化分数</th></tr>
        """
        
        for i, scene in enumerate(scenes):
            html += f"""
                    <tr>
                        <td>{i+1}</td>
                        <td>{scene.get('start_time', 0):.2f}s</td>
                        <td>{scene.get('end_time', 0):.2f}s</td>
                        <td>{scene.get('duration', 0):.2f}s</td>
                        <td>{scene.get('change_score', 0):.3f}</td>
                    </tr>
            """
        
        html += """
                </table>
            </div>
            
            <div class="section">
                <h2>视觉特征</h2>
        """
        
        color_features = features.get("color_features", {})
        if color_features:
            html += f"""
                <h3>颜色特征</h3>
                <div class="metric">平均亮度: {color_features.get('average_brightness', 0):.2f}</div>
                <div class="metric">平均对比度: {color_features.get('average_contrast', 0):.2f}</div>
            """
        
        if motion_analysis:
            html += f"""
                <h3>运动分析</h3>
                <div class="metric">运动检测: {'是' if motion_analysis.get('motion_detected', False) else '否'}</div>
                <div class="metric">平均运动幅度: {motion_analysis.get('average_motion', 0):.2f}</div>
                <div class="metric">最大运动幅度: {motion_analysis.get('max_motion', 0):.2f}</div>
            """
        
        html += """
            </div>
        </body>
        </html>
        """
        
        return html
    
    def clear_cache(self) -> None:
        """清空分析缓存"""
        self.analysis_cache.clear()
        self.logger.info("分析缓存已清空")
    
    def get_cache_stats(self) -> Dict[str, Any]:
        """获取缓存统计信息"""
        return {
            "cache_size": len(self.analysis_cache),
            "max_concurrent_jobs": self.max_concurrent_jobs
        }
